#pragma implementation "tabctrl.cpp" 
#include "TabCtrl.h"

DEFINE_EVENT_TYPE(wxEVT_TAB_CHANGED)

BEGIN_EVENT_TABLE(wxTabCtrl,wxControl)
  EVT_LEFT_DOWN(wxTabCtrl::OnLeftDown)
  EVT_MOTION(wxTabCtrl::OnMotion)
END_EVENT_TABLE()

  //  EVT_PAINT(wxTabCtrl::OnPaint)

// internal class
class wxTabItem {
public:
  wxTabItem() { width=-1; };
  wxString getTitle() { return mTitle; };
  void setTitle(wxString title) {mTitle=title;};
  long getUserData() { return mUserData; };
  void setUserData(long userData) {mUserData=userData;};
  int getWidth() {return width;};
  void setWidth(int newWidth) {width=newWidth;};
private:
  wxString mTitle;
  long mUserData;
  int width;
};

#include <wx/listimpl.cpp>
WX_DEFINE_LIST(TabList);

IMPLEMENT_DYNAMIC_CLASS(wxTabCtrl,wxControl)

extern wxColour GetColour(wxSystemColour w);

GtkWidget* tmpwid=NULL;

gboolean expose_evt(GtkWidget* widget,GdkEventExpose* evt,gpointer data)
{
  wxTabCtrl* _this=(wxTabCtrl*)data;
  _this->OnPaint(widget,evt);
  return TRUE;
}

bool wxTabCtrl::Create(wxWindow* parent,
		       const wxWindowID id,const wxPoint& pos,
		       const wxSize& size,const long int style)
{
  // create base window
  //if(!wxWindow::Create(parent,id,pos,size,0))
  //  return FALSE;

  if(!PreCreation(parent,pos,size) ||
     !CreateBase(parent,id,pos,size,style)) {
    printf("Error.\n");
    return FALSE;
  }

  m_widget=gtk_drawing_area_new();

  // we need the notebook's style..
  tmpwid=gtk_notebook_new();
  GtkStyle* newstyle=gtk_rc_get_style(tmpwid);
  if(!newstyle) newstyle=gtk_widget_get_default_style();
  newstyle=gtk_style_copy(newstyle);
  gtk_style_ref(newstyle);
  gtk_widget_set_style(m_widget,newstyle);

  gtk_signal_connect(GTK_OBJECT(m_widget),"expose_event",GTK_SIGNAL_FUNC(expose_evt),this);
  gtk_widget_destroy(tmpwid);

  m_parent->DoAddChild(this);
  PostCreation();
  SetBestSize(size);
  Show(TRUE);

  //SetBackgroundColour(GetColour(wxSYS_COLOUR_WINDOW));
  m_tabs.Clear();
  currentTab=0;
  firstTab=0;
  prelightRight=false;
  prelightLeft=false;

  Refresh();
}

int wxTabCtrl::calcTabWidth() {
  int width=0;
  TabList::Node* n=m_tabs.GetFirst();
  while(n) {
    wxTabItem* ni=n->GetData();
    width+=ni->getWidth();
    n=n->GetNext();
  }
  return width;
}

long wxTabCtrl::InsertItem(int nMask,int nItem,wxString title,int nImage,long lpar)
{
  wxTabItem* ni=new wxTabItem();
  ni->setTitle(title);
  ni->setUserData(lpar);
  ni->setWidth(-1); // ensure resize at first paint
  TabList::Node* node=m_tabs.Insert(nItem,ni);
  return m_tabs.IndexOf(ni);
}

void wxTabCtrl::OnMotion(wxMouseEvent& evt)
{
  wxRect myrcx=GetRect();

  if(myrcx.width/calcTabWidth()>m_tabs.GetCount())
    return;
  bool oldRight=prelightRight;
  bool oldLeft=prelightLeft;
  if(evt.GetX()>myrcx.width-11) {
    prelightRight=true;
  } else {
    prelightRight=false;
  }
  if(evt.GetX()>myrcx.width-21 && evt.GetX()<myrcx.width-11) {
    prelightLeft=true;
  } else {
    prelightLeft=false;
  }
  if((oldRight!=prelightRight)||(oldLeft!=prelightLeft)) {
    Refresh(FALSE);
  }
}

int wxTabCtrl::tabsVisible()
{ 
  wxRect myrcx=GetRect();
  if(myrcx.width/calcTabWidth()>m_tabs.GetCount())
    return m_tabs.GetCount();
  return (myrcx.width/calcTabWidth());
}

void wxTabCtrl::OnLeftDown(wxMouseEvent& evt)
{
  if(m_tabs.GetCount()>tabsVisible()) {
    wxRect rc=GetRect();
    if(evt.GetX()>rc.width-11) {
      // skroll
      if(firstTab+tabsVisible()<m_tabs.GetCount()) {
	firstTab++;
	Refresh(FALSE);
      }
      return;
    }
    if(evt.GetX()>rc.width-21) {
      // skroll
      if(firstTab>0) {
	firstTab--;
	Refresh(FALSE);
      }
      return;
    }
  }

  int newTab=(evt.GetX()/100); // hmm..

  if(newTab>tabsVisible()-1)
    return;
  if(newTab<0) 
    return;

  currentTab=firstTab+newTab;

  Refresh(FALSE);

  // emit event
  wxCommandEvent ev(wxEVT_TAB_CHANGED,GetId());
  GetEventHandler()->ProcessEvent(ev);
}

void wxTabCtrl::OnPaint(GtkWidget* widget,GdkEventExpose* evt)
{
  wxRect myrcx=GetRect();
  printf("rc=%d %d %d %d\n",myrcx.x,myrcx.y,myrcx.width,myrcx.height);
  // get the style
  gtk_widget_reset_rc_styles(m_widget);
  GtkStyle* style=gtk_rc_get_style(m_widget);//=m_widget->style;//gtk_widget_get_style(m_widget);
  GdkRectangle myrc={evt->area.x,evt->area.y,evt->area.width,evt->area.height};//myrcx.x,myrcx.y,myrcx.width,myrcx.height};

  // draw inactive tabs
  int ythickness;
#ifdef __GTK2__
  ythickness=m_widget->style->ythickness;
#else
  ythickness=widget->style->klass->ythickness;
#endif

  int xc=0;
  for(int i=firstTab;i<m_tabs.GetCount();i++) {
    wxTabItem* item=m_tabs.Item(i)->GetData();
    if(item->getWidth()==(-1)) {
      // need to recalculate the width
      int newwid=0;
#ifdef __GTK2__
      newwid=10; // ugly hack to ensure width > 0
#else
      newwid=gdk_string_width(widget->style->font,item->getTitle());
#endif
     item->setWidth(newwid);
    }

    if(xc+item->getWidth()>(myrcx.width-20)) break; // don't draw tabs outside the window 

    if(i!=currentTab) {
      gtk_paint_flat_box(widget->style,widget->window,
			 GTK_STATE_NORMAL,GTK_SHADOW_NONE,
			 &myrc,widget,"tab",
			 xc,4,item->getWidth(),24+2*ythickness);
      gtk_paint_extension(widget->style,widget->window,
			  GTK_STATE_ACTIVE,GTK_SHADOW_OUT,
			  &myrc,widget,
			  "tab",xc,4+2*ythickness,item->getWidth(),24,GTK_POS_BOTTOM);
      gtk_paint_string(widget->style,widget->window,
		       GTK_STATE_NORMAL,
		       &myrc,widget,
		       "tab",xc+10,4+15+2*ythickness,item->getTitle());
    }
    xc+=item->getWidth();
  }

  // then draw active tab
  gtk_paint_extension(widget->style,widget->window,
		      GTK_STATE_NORMAL,GTK_SHADOW_OUT,
		      &myrc,widget,
		      "tab",(currentTab-firstTab)*100,4,100,24+2*ythickness,GTK_POS_BOTTOM);
  
  gtk_paint_string(widget->style,widget->window,
		   GTK_STATE_ACTIVE,
		   &myrc,widget,
		   "tab",(currentTab-firstTab)*100+10,4+15,
		   m_tabs.Item(currentTab)->GetData()->getTitle());

  // paint arrows only if necessary
  if(m_tabs.GetCount()>tabsVisible()) {
    GtkStateType state=GTK_STATE_NORMAL;
    if(prelightLeft) state=GTK_STATE_INSENSITIVE;
    gtk_paint_arrow(widget->style,widget->window,
		    state,GTK_SHADOW_ETCHED_OUT,
		    &myrc,widget,
		    "notebook",GTK_ARROW_LEFT,TRUE,
		    myrcx.width-20,20,16,16);
    state=GTK_STATE_NORMAL;
    if(prelightRight) state=GTK_STATE_INSENSITIVE;
    gtk_paint_arrow(widget->style,widget->window,
		    state,GTK_SHADOW_ETCHED_OUT,
		    &myrc,widget,
		    "notebook",GTK_ARROW_RIGHT,TRUE,
		    myrcx.width-10,20,16,16);
  }
}
